package main

import (
	"fmt"
	"log"
	"net"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
)

var LocalIP = "192.168.1.120"         // 本机IP，用于找到对应的网卡
var expectedMAC = "00:E0:99:FE:0E:9B" // 要查找的目标MAC地址

func main() {
	// 获取所有网络接口
	devices, err := pcap.FindAllDevs()
	if err != nil {
		log.Fatalf("无法获取网卡列表: %v", err)
	}

	var ifaceName string
	for _, dev := range devices {
		for _, addr := range dev.Addresses {
			if addr.IP.String() == LocalIP {
				ifaceName = dev.Name
				break
			}
		}
		if ifaceName != "" {
			break
		}
	}
	if ifaceName == "" {
		log.Fatalf("未找到与 LocalIP %s 匹配的网卡", LocalIP)
	}
	fmt.Printf("匹配到网卡: %s\n", ifaceName)

	// 获取 net.Interface 对象
	netIface, err := findNetInterfaceByIP(LocalIP)
	if err != nil {
		log.Fatalf("查找网卡信息失败: %v", err)
	}

	// 执行ARP反查
	found, ip := arpProbeFindIPByMAC(ifaceName, netIface, expectedMAC)
	if found {
		fmt.Printf("✅ 找到目标MAC %s 对应的IP: %s\n", expectedMAC, ip)
	} else {
		fmt.Println("❌ 未找到目标MAC对应的IP")
	}
}

// 通过ARP广播查找指定expectedMAC对应的IP
func arpProbeFindIPByMAC(pcapIfaceName string, netIface *net.Interface, expectedMAC string) (bool, string) {
	srcIP, err := getInterfaceIPv4(netIface)
	if err != nil {
		log.Fatal(err)
	}

	buf := gopacket.NewSerializeBuffer()
	opts := gopacket.SerializeOptions{FixLengths: true, ComputeChecksums: true}

	ether := &layers.Ethernet{
		SrcMAC:       netIface.HardwareAddr,
		DstMAC:       net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
		EthernetType: layers.EthernetTypeARP,
	}

	arp := &layers.ARP{
		Operation:         layers.ARPRequest,
		SourceHwAddress:   netIface.HardwareAddr,
		SourceProtAddress: srcIP.To4(),
		DstHwAddress:      []byte{0, 0, 0, 0, 0, 0},
		DstProtAddress:    []byte{0, 0, 0, 0}, // 广播请求
		HwAddressSize:     6,
		ProtAddressSize:   4,
	}

	if err := gopacket.SerializeLayers(buf, opts, ether, arp); err != nil {
		log.Fatal(err)
	}

	log.Printf("发送ARP广播请求，查找目标MAC=%s", expectedMAC)

	handle, err := pcap.OpenLive(pcapIfaceName, 65536, true, pcap.BlockForever)
	if err != nil {
		log.Fatal(err)
	}
	defer handle.Close()

	if err := handle.WritePacketData(buf.Bytes()); err != nil {
		log.Printf("发送ARP失败: %v", err)
		return false, ""
	}

	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	timeout := time.After(3 * time.Second)

	for {
		select {
		case <-timeout:
			return false, ""
		case packet := <-packetSource.Packets():
			arpLayer := packet.Layer(layers.LayerTypeARP)
			if arpLayer == nil {
				continue
			}
			reply := arpLayer.(*layers.ARP)
			mac := net.HardwareAddr(reply.SourceHwAddress).String()
			ip := net.IP(reply.SourceProtAddress).String()

			log.Printf("收到ARP应答: IP=%s, MAC=%s", ip, mac)

			if reply.Operation == layers.ARPReply && mac == expectedMAC {
				return true, ip
			}
		}
	}
}

// 获取本地网卡IPv4
func getInterfaceIPv4(iface *net.Interface) (net.IP, error) {
	addrs, err := iface.Addrs()
	if err != nil {
		return nil, err
	}
	for _, addr := range addrs {
		if ipnet, ok := addr.(*net.IPNet); ok {
			if ipv4 := ipnet.IP.To4(); ipv4 != nil {
				return ipv4, nil
			}
		}
	}
	return nil, fmt.Errorf("未找到IPv4地址")
}

// 根据IP获取网卡接口
func findNetInterfaceByIP(ip string) (*net.Interface, error) {
	interfaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	for _, iface := range interfaces {
		addrs, _ := iface.Addrs()
		for _, addr := range addrs {
			if ipnet, ok := addr.(*net.IPNet); ok {
				if ipnet.IP.String() == ip {
					return &iface, nil
				}
			}
		}
	}
	return nil, fmt.Errorf("未找到包含IP %s 的网卡", ip)
}
